/*
 * Created on 2008-7-29
 *
 * TODO
 */
package jacky.lanlan.song.extension.hibernate;

import org.hibernate.cfg.*;
import org.springframework.beans.factory.FactoryBean;

import jacky.lanlan.song.util.Assert;

/**
 * <code>NamingStrategy</code> 的工厂Bean，由于Hibernate自身提供的 <code>NamingStrategy</code> 已经通过static构造
 * 产生了singleton，所以没有必要用Spring再去构造一个singleton，故使用这个类。
 * <p>
 * 内置Hibernate默认提供的 <code>NamingStrategy</code>，也可以注入自定义的 <code>NamingStrategy</code>。
 * <p>
 * 该工厂默认产生 <code>DefaultNamingStrategy</code>。
 * 
 * @author Jacky.Song
 */
public class NamingStrategyFactoryBean implements FactoryBean {

	private NamingStrategy ns = DefaultNamingStrategy.INSTANCE;
	
	/**
	 * 设置要使用的<code>NamingStrategy</code>类名。
	 * <p>
	 * 要使用内置的<code>NamingStrategy</code>，可以传递对应的简称（去除引号）：
	 * <p>
	 * <table border="1">
	 * <tr>
	 * <th width="50%">"default"</th>
	 * <td><code>DefaultNamingStrategy</code></td>
	 * </tr>
	 * <tr>
	 * <th width="50%">"improved"</th>
	 * <td><code>ImprovedNamingStrategy</code></td>
	 * </tr>
	 * <tr>
	 * <th width="50%">"ejb3"</th>
	 * <td><code>EJB3NamingStrategy</code></td>
	 * </tr>
	 * <tr>
	 * <th width="50%">"default_component"</th>
	 * <td><code>DefaultNamingStrategy</code></td>
	 * </tr>
	 * </table>
	 * 
	 * @param className
	 * @throws ClassNotFoundException
	 */
	public void setNamingStrategy(String className) throws ClassNotFoundException {
		if (className.equalsIgnoreCase("default")) {
			ns = DefaultNamingStrategy.INSTANCE;
		}
		else if (className.equalsIgnoreCase("improved")) {
			ns = ImprovedNamingStrategy.INSTANCE;
		}
		else if (className.equalsIgnoreCase("ejb3")) {
			ns = EJB3NamingStrategy.INSTANCE;
		}
		else if (className.equalsIgnoreCase("default_component")) {
			ns = DefaultComponentSafeNamingStrategy.INSTANCE;
		}
		else {
			Class<?> namingStrategyClass = Class.forName(className);
			Assert.isTrue(NamingStrategy.class.isAssignableFrom(namingStrategyClass), "必须是一个NamingStrategy");
			try {
				ns = (NamingStrategy) namingStrategyClass.newInstance();
			}
			catch (Exception e) {
				throw new RuntimeException("不能创建 [" + className + "] " + e);
			}
		}
	}
	
	public Object getObject() throws Exception {
		return ns;
	}
	
	public Class getObjectType() {
		return ns.getClass();
	}
	
	public boolean isSingleton() {
		return true;
	}

}
